當使用某種類型的值調用一個函式,而此函式實際上需要另一種類型的值時,JavaScript會嘗試自動將其轉換為需要的類型。
比如,若寫一個函式需要一個字串引數,但調用它時卻傳遞了一個不同類型的值,那麼 JavaScript 會嘗試將這個值轉換為字串使函式能夠正確運作。
這對於原始資料型別 (primitive data type,如 number
、boolean
、null
、undefined
等) 是有效的,而所有物件也都擁有 toString()
方法(但實際行為不一定總是返回有用的結果), 因此在這些情況下,不太可能發生錯誤:
// 整數相加
var num1 = 5;
var num2 = 10;
var result = num1 + num2;
console.log(result); // 15
// 整數和字串相加
var num = 5;
var str = "10";
var result = num + str;
console.log(result); // "510"
// 布林值與數字相加
var bool = true;
var num = 7;
var result = bool + num;
console.log(result); // 結果是數字8(true轉換為1)
// null和undefined的轉換
var value1 = null;
var value2 = undefined;
var result1 = value1 + 10;
var result2 = value2 + "hello";
console.log(result1); // 結果是數字 10(null轉換為0)
console.log(result2); // 結果是字串 "undefinedhello"
// 物件的toString()方法
var obj = { name: "John" };
var str = obj.toString();
console.log(str); // str現在包含字串 "[object Object]"
// 物件的隱式轉換
var num = 42;
var obj = { value: 10 };
var result = num + obj; // 結果是字串 "42",因為num被轉換為字串,然後與obj的字串結合
console.log(result); // "42[object Object]"
JavaScript會根據需要自動執行類型轉換,所以通常不會導致錯誤,但這種情況並非永遠成立,有時可能導致意外的結果,因此在撰寫程式碼時需要謹慎處理類型轉換。
書中提到的 arraycopy()
範例 ,它要求其第一個引數必須是一個陣列。若傳給 arraycopy()
函式的第一個引數不是陣列或類似陣列的物件,那麼任何合理的、正確實現 arraycopy()
函式的程式碼都不會運作正確,從而導致錯誤。 這是因為 arraycopy()
函式的設計和預期是要處理陣列,而不是其他類型的物件:
// 書中範例
/*
型別 array : from,
型別 index : from_start,
型別 array : to,
型別 index : to_start,
型別 integer : length
*/
function arraycopy(from, from_start, to, to_start, length){
//程式碼
}
因此,除非寫的是一個只會被調用一兩次的一次性函式,否則最好增加檢查函式引數類型的程式碼。好處是,若傳遞了不正確的引數,函式會立即拋出錯誤,避免不正確的引數導致後續執行中的錯誤。
一次性函式: 很少次被呼叫的函式,而不是常見的或被多次使用的函式。
isArrayLike()
的函式來確保引數類似陣列若引數是類似陣列的,則函式會計算這些元素的總和,並忽略
null
和undefined
值。
// 書中範例
// 返回陣列(或類似陣列物件)a的元素之和。
// a的元素必須都是數字,而 null 和 undefined 會被忽略。
function sum(a) {
if (isArrayLike(a)) {
var total = 0;
for (var i = 0; i < a.length; i++) {
// 遍歷所有元素
var element = a[i];
if (element == null) {
continue; // 跳過null和undefined
}
if (isFinite(element)) {
total += element;
} else throw new Error("sum(): elements must be finite numbers"); // 若元素不是有限數字,會拋出錯誤資訊
}
return total;
} else throw new Error("sum(): argument must be array-like"); // 若引數不是類似陣列,會拋出錯誤資訊。
}
JavaScript 可以自動進行類型轉換以適應需要的型別。
以 Boolean 為例:
true
,而其他值被稱為 falsy,它們轉換為false
。可參考 JS Comparison Table、 相等比較 - JavaScript | MDN
以字串為例:
以數字為例
NaN
(Not-a-Number)。console.log(5 + " objects") // "5 objects" 數字10轉為字串
console.log("6" + "20") // 620: 兩個字串都轉成數字
console.log("6" * "6") // 36: 兩個字串都轉成數字
var n = 3 - "a";
console.log(n); // NaN: 字串 "a" 不能轉為數字
console.log(n + " object"); // "NaN objects": NaN 轉為字串 'NaN'